from django.views.generic import View
from libs import json_response, JsonParser, Argument
from apps.tool.models import VpnServer, VpnUser
from apps.account.models import Role
from libs import human_datetime, AttrDict
from libs.pritunl_v2 import Pritunl
from libs.saas_openvpn import SaasOvpn
from libs.huaweicloud_ovpn import HuaweicloudOvpn
from libs.validators import mailaddress_validator
from libs.mail import send_email

import random


class VpnServerView(View):
    def get(self, request):
        vpnserver_id = request.GET.get('id')
        if vpnserver_id:
            return json_response(VpnServer.objects.get(pk=vpnserver_id))
        vpnservers = VpnServer.objects.filter(deleted_by_id__isnull=True)

        return json_response(vpnservers)

    def post(self, request):
        serverid_required = False
        type, error = JsonParser(
            Argument('type', handler=str.strip, help='请输入VPN服务器类型'),
        ).parse(request.body)
        if type.type is None:
            pass
        else:
            if type.type == 'pritunl':
                serverid_required = True
        form, error = JsonParser(
            Argument('id', type=int, required=False),
            Argument('url', help='请输入VPN管理链接'),
            Argument('name', help='请输入VPN服务器名称'),
            Argument('type', handler=str.strip, help='请输入VPN服务器类型'),
            Argument('username', required=serverid_required, handler=str.strip, help='请输入用户名'),
            Argument('password', required=serverid_required, handler=str.strip, help='请输入密码'),
            Argument('serverid', required=serverid_required, handler=str.strip, help='请输入pritunl serverid'),
            Argument('desc', required=False),
        ).parse(request.body)

        if error is None:
            if form.id:
                # 如果传的参数带id,则更新IDC
                VpnServer.objects.filter(pk=form.pop('id')).update(**form)
            elif VpnServer.objects.filter(name=form.name, deleted_by_id__isnull=True).exists():
                # VpnServer名称唯一，如果已存在相同的VpnServer名称则报错
                return json_response(error=f'已存在的VpnServer名称【{form.name}】')
            else:
                # 新建IDC记录
                vpnserver = VpnServer.objects.create(created_by=request.user, **form)
                if request.user.role:
                    request.user.role.add_host_perm(vpnserver.id)
        return json_response(error=error)

    def delete(self, request):
        form, error = JsonParser(
            Argument('id', type=int, help='请指定操作对象')
        ).parse(request.GET)
        if error is None:
            vpnuser = VpnUser.objects.filter(vpnserver_id=form.id, deleted_by_id__isnull=True).first()
            if vpnuser:
                return json_response(error=f'VPN用户【{vpnuser.name}】关联了该VPN服务器，请解除关联后再尝试删除该VPN')
            VpnServer.objects.filter(pk=form.id).update(
                deleted_at=human_datetime(),
                deleted_by=request.user,
            )
        return json_response(error=error)


class VpnUserView(View):
    def get(self, request):
        vpnuser_id = request.GET.get('id')
        if vpnuser_id:
            return json_response(VpnUser.objects.get(pk=vpnuser_id))
        vpnusers = VpnUser.objects.filter(deleted_by_id__isnull=True)
        perms = [x.id for x in vpnusers]
        vpnservers = VpnServer.objects.filter(deleted_by_id__isnull=True)
        return json_response({'vpnusers': [x.to_dict() for x in vpnusers], 'perms': perms, 'vpnservers': [x.to_dict() for x in vpnservers]})

    def post(self, request):
        form, error = JsonParser(
            Argument('id', type=int, required=False),
            Argument('vpnserver_id', help='请选择VPN服务'),
            Argument('name', help='请输入用户名'),
            Argument('desc', required=False),
        ).parse(request.body)
        if not mailaddress_validator(form.name):
            return json_response(error=f'请输入正确的邮箱地址。')
        if error is None:
            if form.id:
                pass
            elif VpnUser.objects.filter(name=form.name, vpnserver_id=form.vpnserver_id, deleted_by_id__isnull=True).exists():
                return json_response(error=f'已存在的VPN用户【{form.name}】')
            else:
                form['email'] = form.name
                # 创建
                vpnserver = VpnServer.objects.filter(pk=form.vpnserver_id).first()
                client = get_vpn_client(vpnserver)
                add_vpn_user(client, form.name)
                vpnuser = VpnUser.objects.create(created_by=request.user, **form)
                if request.user.role:
                    request.user.role.add_host_perm(vpnuser.id)
        return json_response(error=error)

    def delete(self, request):
        form, error = JsonParser(
            Argument('id', type=int, help='请指定操作对象')
        ).parse(request.GET)
        if error is None:

            vpnuser_queryset = VpnUser.objects.filter(pk=form.id)
            vpnuser_queryset.update(deleted_at=human_datetime(), deleted_by=request.user,)
            vpnuser = vpnuser_queryset.first()
            vpnserver = VpnServer.objects.filter(pk=vpnuser.vpnserver_id).first()
            if vpnserver.type in ('huaweicloud', 'fastapi'):
                return json_response(error=f"此类型VPN服务暂不支持在线删除用户。")
            client = get_vpn_client(vpnserver)
            res = client.userdel(vpnuser.name)

        return json_response(error=error)


def get_vpn_client(vpnserver):
    if vpnserver.type == 'pritunl':
        client = Pritunl(vpnserver.url, vpnserver.serverid, vpnserver.username, vpnserver.password)
    elif vpnserver.type == 'phpadmin' or vpnserver.type == 'saas':
        client = SaasOvpn(vpnserver.url, vpnserver.username, vpnserver.password)
        client.login()
    elif vpnserver.type == 'fastapi' or vpnserver.type == 'huaweicloud':
        client = HuaweicloudOvpn(vpnserver.url, vpnserver.username, vpnserver.password)
        client.login()
    else:
        return False
    return client


def add_vpn_user(client, email):
    random_password = str(random.randint(1000000, 10000000))
    res = client.useradd(email, random_password)
    if res['status']:
        if res['type'] == 'pritunl':
            content = 'VPN文件链接地址为：{} , 请注意保管。\n下载指引参见：https://wiki.tuhu.cn/pages/viewpage.action?pageId=55918949'.format(
                    res['view_url'])
        elif res['type'] == 'phpadmin':
            content = 'VPN文件链接地址为：{} , 请注意保管。\n用户名： {}\n密码： {}\n'.format(
                    res['view_url'], res['username'], res['password'])
        elif res['type'] == 'fastapi':
            content = 'VPN文件链接地址为：{}/vpn , 请注意保管。\n用户名： {}\n密码： {}\n'.format(
                    res['view_url'], res['username'], res['password'])
        else:
            return False
        send_email(content, email)

    return res['status']


def sync_import(request):
    summary = {'create': [], 'update': [], 'invalid': [], 'skip': [], 'fail': [], 'network': [], 'repeat': [], 'success': [], 'error': []}
    vpnserver_id = request.POST.get('vpnserver_id')
    vpnserver = VpnServer.objects.filter(pk=vpnserver_id).first()
    if not vpnserver.username or not vpnserver.password or not vpnserver.url or not vpnserver.type:
        return json_response(error=f'VPN服务关键信息缺失，无法同步。')
    client = get_vpn_client(vpnserver)
    if not client:
        return json_response(error=f'未知的VPN服务类型。')
    users = client.get_all_users()
    if users:
        vpnuser_dict = dict(list(VpnUser.objects.filter(deleted_by_id__isnull=True, vpnserver_id=vpnserver_id).values_list('name', 'vpnserver_id')))
        for user in users:
            user.pop('organization')
            user['vpnserver_id'] = vpnserver_id
            if user['name'] in vpnuser_dict and vpnuser_dict[user['name']] == int(vpnserver_id):
                VpnUser.objects.filter(vpnserver_id=vpnserver_id, name=user['name']).update(**user)
                summary['update'].append(user['name'])
            else:
                VpnUser.objects.create(created_by=request.user, **user)
                summary['create'].append(user['name'])

    return json_response(summary)
